fix(kiloclaw) webhook agent ingest chat delivery#3140
Merged
Conversation
…est-chat-delivery
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (4 files)
Reviewed by gpt-5.5-20260423 · 516,496 tokens |
jeanduplessis
approved these changes
May 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Webhook deliveries that target a KiloClaw chat thread have been failing in production with "Authentication required" errors since the Stream Chat backend was removed. The dead path was a POST from the webhook agent ingest queue consumer to a kiloclaw worker route (
/api/platform/send-chat-message) that no longer exists. Captured webhook requests reach the trigger requests page in the cloud dashboard, attempt delivery, and end up in thefailedstate.This change replaces the dead HTTP fetch with a service binding RPC into the kilo-chat worker. A new
KiloChatService.postMessageAsUsermethod resolves the conversation between the user and the bot, optionally creates one on first delivery, and posts the rendered prompt via the existingcreateMessageForpath. The rest of the pipeline (capture, queue, trigger config, token minting, the cloud agent delivery target) is unchanged.The new RPC is intentionally generic. The
sourceparameter is a free form string used for log attribution, so future internal flows that want to post user messages into the chat thread (for example, an onboarding flow that warms the bot before the user opens chat for the first time) can call the same primitive without a contract change.Reliability and validation guarantees:
textBlockSchemaused by the public createMessage HTTP route, returninginvalid_requestfor empty or oversized bodies before any conversation lookup or creation. Webhook payloads can be up to 256KB, so without this the persisted chat content could exceedMESSAGE_TEXT_MAX_CHARS.inprogress. Without the catch, the outer queue retry guard would silently ack the next attempt and leave the request stuck.userOwnsSandboxunconditionally, including the path where a conversation already exists. The previous behaviour trusted the ConversationDO membership snapshot, which is not equivalent to current sandbox ownership.kiloclaw_instanceslookup in webhook agent ingest is now scoped by user id. A stale or other tenant instance id returns a clean "instance not found" instead of resolving to a different user's sandbox.The cross service RPC contract types live in the shared
@kilocode/kilo-chatpackage so producer (kilo-chat) and consumer (webhook agent ingest) share one source of truth. A drift in either direction now fails the build instead of passing wrong data at runtime.Verification
postMessageAsUser: auto creates a conversation on first delivery, reuses an existing one on subsequent delivery, returnsno_conversationwhenautoCreateConversation: falseand none exists, returnsforbiddenwhen the user does not own the sandbox, returnsforbiddenwhen ownership is revoked between conversation create and a later post (covers the existing conversation bypass), and returnsinvalid_requestfor empty or oversized message bodies.pnpm run lint,pnpm run typecheck, andpnpm run format:checkall clean across both services and the shared package.Visual Changes
N/A
Reviewer Notes
The new RPC accepts
sandboxIdrather thankiloclawInstanceId. The webhook consumer does thekiloclaw_instancestranslation on its side, which keeps kilo-chat free of any kiloclaw specific schema knowledge while the consumer already has database access for upstream trigger lookups.The
getKiloChat(env)cast helper inservices/webhook-agent-ingest/src/kilo-chat-binding.tsexists becausewrangler typesonly emits a genericServicefor service bindings. Centralising the cast keeps call sites clean and gives one place to update if the binding shape ever moves.